//
//  VideoPlayerCell.swift
//  Mediaplayer
//
//  Created by bin hu on 2025/7/8.
//

import UIKit
import AVFoundation

// MARK: - 视频播放单元格
class VideoPlayerCell: UICollectionViewCell {
    
    // MARK: - 属性
    static let identifier = "VideoPlayerCell"
    
    private var player: AVPlayer?
    private var playerLayer: AVPlayerLayer?
    private var playerItem: AVPlayerItem?
    private var playbackRate: Float = 1.0
    private var videoItem: VideoItem?
    
    private var controlView: VideoControlView!
    private var aspectRatioConstraint: NSLayoutConstraint?
    private var loadingIndicator: UIActivityIndicatorView?
    
    // MARK: - 初始化
    override init(frame: CGRect) {
        super.init(frame: frame)
        setupPlayer()
        setupControls()
        setupLoadingIndicator()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    // MARK: - UI设置
    private func setupPlayer() {
        contentView.theme_backgroundColor = "Colors.black"
        
        // 创建播放器层
        playerLayer = AVPlayerLayer()
        playerLayer?.videoGravity = .resizeAspect
        playerLayer?.frame = contentView.bounds
        contentView.layer.addSublayer(playerLayer!)
    }
    
    private func setupControls() {
        controlView = VideoControlView()
        controlView.translatesAutoresizingMaskIntoConstraints = false
        controlView.delegate = self
        contentView.addSubview(controlView)
        
        controlView.snp.makeConstraints { make in
            make.left.right.equalToSuperview()
            make.bottom.equalToSuperview().inset(10)
            make.height.equalTo(50)
        }
    }
    
    private func setupLoadingIndicator() {
        loadingIndicator = UIActivityIndicatorView(style: .large)
        loadingIndicator?.color = .white
        loadingIndicator?.hidesWhenStopped = true
        loadingIndicator?.translatesAutoresizingMaskIntoConstraints = false
        contentView.addSubview(loadingIndicator!)
        
        NSLayoutConstraint.activate([
            loadingIndicator!.centerXAnchor.constraint(equalTo: contentView.centerXAnchor),
            loadingIndicator!.centerYAnchor.constraint(equalTo: contentView.centerYAnchor)
        ])
    }
    
    // MARK: - 配置
    func configure(with videoItem: VideoItem) {
        self.videoItem = videoItem
        resetPlayer()
        
        // 检查是否有本地缓存
        if let localURL = VideoCacheManager.shared.cachedFileURL(for: videoItem.videoUrl) {
            setupPlayer(with: AVAsset(url: localURL))
            return
        }
        
        // 从预加载器获取资源
        if let asset = VideoPreloader.shared.cachedAsset(for: videoItem.videoUrl) {
            setupPlayer(with: asset)
        } else {
            // 直接加载
            let asset = AVURLAsset(url: videoItem.videoUrl)
            setupPlayer(with: asset)
        }
    }
    
    private func setupPlayer(with asset: AVAsset) {
        loadingIndicator?.startAnimating()
        
        playerItem = AVPlayerItem(asset: asset)
        player = AVPlayer(playerItem: playerItem)
        playerLayer?.player = player
        player?.isMuted = true
        player?.rate = playbackRate
        
        // 设置自适应码率
        if #available(iOS 11.0, *) {
            playerItem?.preferredPeakBitRate = VideoPreloader.shared.preferredBitrate
        }
        
        // 监听播放状态
        playerItem?.addObserver(self, forKeyPath: "status", options: .new, context: nil)
        playerItem?.addObserver(self, forKeyPath: "duration", options: .new, context: nil)
        playerItem?.addObserver(self, forKeyPath: "playbackBufferEmpty", options: .new, context: nil)
        playerItem?.addObserver(self, forKeyPath: "playbackLikelyToKeepUp", options: .new, context: nil)
        
        // 添加进度观察
        player?.addPeriodicTimeObserver(
            forInterval: CMTime(seconds: 0.5, preferredTimescale: 600),
            queue: .main
        ) { [weak self] time in
            self?.updateProgress(time: time)
        }
        
        // 添加播放结束监听
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(playerDidFinishPlaying),
            name: .AVPlayerItemDidPlayToEndTime,
            object: playerItem
        )
        
//        // 获取视频尺寸并更新约束
//        asset.loadValuesAsynchronously(forKeys: ["tracks"]) { [weak self] in
//            var error: NSError? = nil
//            let status = asset.statusOfValue(forKey: "tracks", error: &error)
//            
//            if status == .loaded {
//                guard let tracks = asset.tracks(withMediaType: .video) else { return }
//                guard let track = tracks.first else { return }
//                
//                let size = track.naturalSize
//                let ratio = size.height / size.width
//                
//                DispatchQueue.main.async {
//                    self?.updateAspectRatio(ratio)
//                }
//            }
//        }
        
    }
    
    // MARK: - 播放控制
    func play() {
        player?.play()
        player?.rate = playbackRate
        controlView.setPlaybackState(true)
    }
    
    func pause() {
        player?.pause()
        controlView.setPlaybackState(false)
    }
    
    @objc private func playerDidFinishPlaying() {
        player?.seek(to: .zero)
        player?.play()
    }
    
    // MARK: - KVO
    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        if keyPath == "status", let item = playerItem {
            if item.status == .readyToPlay {
                loadingIndicator?.stopAnimating()
                controlView.setDuration(item.duration.seconds)
            } else if item.status == .failed {
                print("Player item failed to load: \(item.error?.localizedDescription ?? "Unknown error")")
                loadingIndicator?.stopAnimating()
            }
        } else if keyPath == "duration", let item = playerItem {
            if item.status == .readyToPlay {
                controlView.setDuration(item.duration.seconds)
            }
        } else if keyPath == "playbackBufferEmpty" {
            if playerItem?.isPlaybackBufferEmpty == true {
                loadingIndicator?.startAnimating()
            }
        } else if keyPath == "playbackLikelyToKeepUp" {
            if playerItem?.isPlaybackLikelyToKeepUp == true {
                loadingIndicator?.stopAnimating()
            }
        }
    }
    
    // MARK: - 进度更新
    private func updateProgress(time: CMTime) {
        let progress = Float(time.seconds / (playerItem?.duration.seconds ?? 1.0))
        controlView.setProgress(progress, currentTime: time.seconds)
    }
    
    // MARK: - 清理
    private func resetPlayer() {
        player?.pause()
        player?.replaceCurrentItem(with: nil)
        
        if let item = playerItem {
            item.removeObserver(self, forKeyPath: "status")
            item.removeObserver(self, forKeyPath: "duration")
            item.removeObserver(self, forKeyPath: "playbackBufferEmpty")
            item.removeObserver(self, forKeyPath: "playbackLikelyToKeepUp")
            NotificationCenter.default.removeObserver(self, name: .AVPlayerItemDidPlayToEndTime, object: item)
        }
        
        playerItem = nil
        player = nil
    }
    
    deinit {
        resetPlayer()
    }
}

extension VideoPlayerCell: VideoControlViewDelegate {
    func didChangePlaybackRate(_ rate: Float) {
        playbackRate = rate
        player?.rate = rate
    }
    
    func didSeekTo(_ progress: Float) {
        guard let duration = playerItem?.duration else { return }
        let totalSeconds = CMTimeGetSeconds(duration)
        let targetTime = CMTime(seconds: Double(progress) * totalSeconds, preferredTimescale: 600)
        
        player?.seek(to: targetTime, toleranceBefore: .zero, toleranceAfter: .zero) { [weak self] _ in
            self?.player?.play()
            self?.player?.rate = self?.playbackRate ?? 1.0
        }
    }
    
    func didTogglePlayPause() {
        if player?.rate == 0 {
            play()
        } else {
            pause()
        }
    }
}
